﻿#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//4个默认成员函数，默认的意思就是指我们不写，编译器会变我们⾃动⽣成⼀个，那么在⼦类中，这⼏
//个成员函数是如何⽣成的呢？
//1. ⼦类的构造函数必须调⽤⽗类的构造函数初始化⽗类的那⼀部分成员。如果⽗类没有默认的构造函
//数，则必须在⼦类构造函数的初始化列表阶段显⽰调⽤。
//2. ⼦类的拷⻉构造函数必须调⽤⽗类的拷⻉构造完成⽗类的拷⻉初始化。
//3. ⼦类的operator = 必须要调⽤⽗类的operator = 完成⽗类的复制。需要注意的是⼦类的operator = 隐
//藏了⽗类的operator = ，所以显⽰调⽤⽗类的operator = ，需要指定⽗类作⽤域
//4. ⼦类的析构函数会在被调⽤完成后⾃动调⽤⽗类的析构函数清理⽗类成员。因为这样才能保证⼦类
//对象先清理⼦类成员再清理⽗类成员的顺序。

class Base
{
public:
	Base() {

	}
	Base(int a):_a(a) {

	}
	Base(const Base& b) {
		_a = b._a;
	}
	void operator=(const Base& b) {
		_a = b._a;
	}
	~Base() {

	}
	int _a;
};
class Derive:public Base {
public:
	Derive(){

	}
	Derive(int b,string str):_b(b),_str(str) {

	}

	//一、
	Derive(int a,int b,string str) :Base(a),_b(b),_str(str) {
		    //如果⽗类没有默认的构造函
			//数，则必须在⼦类构造函数的初始化列表阶段显⽰调⽤。
	}

	//二、默认拷贝构造
	// 
	//一般来说，编译器自动生成的拷贝构造已经满足需求了（内置类型的成员发生值拷贝，
	//自定义类型的成员调用自身的拷贝构造，如string _str=str ,调用自身拷贝构造
	//父类也会调用父类的拷贝构造
    //但是若子类的成员变量有自个开的空间，就需要进行深拷贝操作
	Derive(const Derive& d):_b(d._b),_str(d._str),Base(d) {
		 //需要在初始化列表显示调用Base的拷贝构造
		 //子类对象可以赋值给父类对象，完成父类的拷贝构造，即“切片”
		//也需要注意的是，初始化列表的初始化顺序和成员声明的顺序是一致的，
		//这里先初始化父类，再初始化_b,_str 


		//深拷贝操作：......
	}

	//三、默认operator=
	// 
	//一般来说，编译器自动生成的operator=可以满足对象赋值需求（内置类型成员发生值赋值，
	//自定义类型成员调用自身的operator=,父类调用自身的operator=）
	//但是若子类的成员变量有自个开的空间，就需要进行深拷贝操作

	void operator=(const Derive& d) {
		Base::operator=(d); //由于父类和子类的operator=函数名相同，子类隐藏了父类的operator=
		                    //所以要显示调用：Base::operator=()
		_b = d._b;
		_str = d._str;

		//深拷贝操作：
		//......

	}


	//四、默认析构函数
	// 
	//一般来说，编译器自动生成的析构函数可以满足对象销毁操作
	//（自定义类型成员调用自身的析构函数,父类调用自身的析构函数）
	//但是若子类的成员变量有自个开的空间，就需要进行手动释放

	~Derive() {
		Base::~Base(); //需要显示调用父类的析构函数，且要指明作用域，因为编译器
		              //会将所有对象（包括不同类的对象）的析构函数都封装成Destructor()
		              //因此需要指明作用域来调用Base的析构函数

		//delete ...

		//注意：必须要先调用父类的析构函数才能delete子类的空间
		//这样才能保证：父类先析构然后再析构子类的顺序

	}
	void Print() {
		cout << "_a: " << _a << "_b: " << _b << "  " << _str << endl;
	}
private:
	int _b;
	string _str;
	
	//int* p = new int;
};
void test()
{
	Derive d(1,"bit");
	Derive d1(99, 10,"hello hlp");
	Derive d2 = d1; //拷贝构造
	d = d1;
	d.Print();
}
int main()
{
	test();
	return 0;
}